use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{Instruction, BytecodeReader, self}, rtda::Frame};

#[derive(Debug, Default)]
pub struct INVOKE_STATIC {
    index: usize, //被调用的方法的符号引用（CONSTANT_Methodref_info或者CONSTANT_InterfaceMethodref_info常量）
}

impl Instruction for INVOKE_STATIC {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u16() as usize;
    }

    // 从静态变量中取出相应的值，然后推入操作数栈顶。
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let cp = frame.borrow().get_method().get_class().get_constant_pool().unwrap();
        let method_ref = cp.get_constant(self.index).unwrap().method_ref();
        let resolved_method = method_ref.lock().unwrap().resolved_method();
        // 非静态字段，抛出异常
        if !resolved_method.is_static() {
            panic!("java.lang.IncompatibleClassChangeError")
        }
        // print!("line {} code: {:?}", *LINE.lock().unwrap(), resolved_method.borrow().get_code().clone());
        let class = resolved_method.get_class_ptr();
        // init class
        if !class.init_started() {
            // 获取到此锁可进行初始化。
            let init_lock = class.get_init_lock();
            let _lock = init_lock.lock().unwrap();
            // TODO 231028 不清楚为什么不直接往下执行，而是在执行一次此指令，后续测试。
            // 当前帧的nextPC字段已经指向下一条指令，所以需要修改nextPC，让它重新指向当前指令。
            frame.borrow_mut().revert_next_pc();
            // 再次判断，若在其他线程初始化后获取到锁则跳过初始化
            if !class.init_started() {
                base::init_class(frame.borrow().get_thread(), class);
            }
            return;
        }

        base::invoke_method(frame, resolved_method);
    }


}
